/*
 * TestDumpCCType.c
 *
 *  Created on: 2012/05/31
 *      Author: guanxiaoying
 */
#include "TestDump.h"

static VOID ccOutputTypeNamePrefix( AST astType, S4 stunlvl  );
static VOID ccOutputTypeNamePostfix( AST astType  )
{
	AST astOrg;
	AST astDefChain;
	AST astIdx;
	AST astParamType;
	CHAR szBuffer[50]="";


	if( CTypeInfo.isBasicType( astType ) )
	{
		;
	}
	else if( CTypeInfo.isArray( astType ) )
	{

		sprintf( szBuffer, "[%lu]",
				CTypeInfo.getTypeSize( astType ) );
		dumpParameterStr( szBuffer  );
		astOrg = CTypeInfo.getElementType( astType );
		if( astOrg )
		{
			ccOutputTypeNamePostfix( astOrg );
		}
	}
	else if( CTypeInfo.isPointer( astType ))
	{
		astOrg = CTypeInfo.getElementType( astType );
		if( CTypeInfo.isArray( astOrg ) || CTypeInfo.isFunction( astOrg ) )
		{
			dumpParameterStr( ")" );
		}
		ccOutputTypeNamePostfix( astOrg );
	}
	else if( CTypeInfo.isStruct( astType ) )
	{
		;
	}
	else if( CTypeInfo.isUnion( astType ) )
	{
		;
	}
	else if( CTypeInfo.isEnum( astType ) )
	{
		;
	}
	else if( CTypeInfo.isFunction( astType )  )
	{


		dumpParameterStr( "(" );
		astDefChain = CTypeInfo.getMemberChain( astType );
		if( astDefChain == 0 )
		{
			strcat( szBuffer, "void" );
		}
		else
		{
			BOOL bFirst = TRUE;
			while( astDefChain )
			{
				astIdx =CUniteChain.getSymbol(astDefChain) ;
				if( astIdx )
				{
					if( !bFirst ){
						dumpParameterStr(", ");
					}
					bFirst = FALSE;
					astParamType = CSymbol.getType( astIdx );
					ccOutputTypeNamePrefix( astParamType, 0 );
					dumpParameterStr(" ");
					dumpParameterStr(CSymbol.getName( astIdx));
					ccOutputTypeNamePostfix( astParamType );
				}else{
					if( bFirst || CUniteChain.getNextOne( astDefChain ) ){
						if( !bFirst ){
							dumpParameterStr(", ");
						}
						bFirst = FALSE;
						dumpParameterStr( dumpGetStr( XML_ERROR ) );
					}else{
						break;
					}
				}
				astDefChain = CUniteChain.getNextOne( astDefChain );
			}
			if( astDefChain != 0 ){
				if( !bFirst ){
					dumpParameterStr(", ... ");
				}
			}
		}

		dumpParameterStr(  ")" );
		astOrg = CTypeInfo.getElementType( astType );
		if( astOrg )
		{
			ccOutputTypeNamePostfix( astOrg );
		}
	}
	else
	{
		sprintf( szBuffer, ":%lu",
				CTypeInfo.getTypeSize( astType ) );
		dumpParameterStr( szBuffer  );
	}

}
static VOID ccOutputTypeNamePrefix( AST astType, S4 stunlvl  )
{
	AST astOrg;
	AST astDefChain;
	AST astIdx;
	AST astMemType;
	PSZ name;
	BOOL bAddSpace = FALSE;

	if( CTypeInfo.isBasicType( astType ) )
	{
		bAddSpace = FALSE;
		if( CTypeInfo.isVolatile( astType ) )
		{
			dumpParameterStr( "volatile" );
			bAddSpace = TRUE;
		}
		if( CTypeInfo.isConst( astType ) )
		{
			if( bAddSpace )
			{
				dumpParameterStr(  " " );
			}
			dumpParameterStr( "const" );
			bAddSpace = TRUE;
		}
		if( CTypeInfo.isRestrict( astType ) )
		{
			if( bAddSpace )
			{
				dumpParameterStr( " " );
			}
			dumpParameterStr(  "restrict" );
		}
		astOrg = CTypeInfo.getNoneQualifierType( astType );
		if( bAddSpace )
		{
			dumpParameterStr( " " );
		}
		name = CTypeInfo.getBasicTypeName ( astOrg );
		if (name == NULL ){
			dumpParameterStr( dumpGetStr( XML_ERROR ) );
		}else{
			dumpParameterStr(name);
		}
	}
	else if( CTypeInfo.isArray( astType ) )
	{
		astOrg = CTypeInfo.getElementType( astType );
		if( astOrg )
		{
			ccOutputTypeNamePrefix( astOrg, stunlvl );
		}
	}
	else if( CTypeInfo.isPointer( astType ) )
	{
		astOrg = CTypeInfo.getElementType( astType );
		if( astOrg ){
			ccOutputTypeNamePrefix( astOrg , stunlvl);
		}
		if( CTypeInfo.isArray( astOrg ) || CTypeInfo.isFunction( astOrg ) )
		{
			dumpParameterStr( "(" );
		}
		dumpParameterStr( "*" );
		if( CTypeInfo.isVolatile( astType ) )
		{
			dumpParameterStr( " volatile" );
		}
		if( CTypeInfo.isConst( astType ) )
		{
			dumpParameterStr( " const" );
		}
		if( CTypeInfo.isRestrict( astType ) )
		{
			dumpParameterStr(  " restrict" );
		}
	}
	else if(CTypeInfo.isStruct( astType ) )
	{
		AST astSym = CTypeInfo.getTagInfo( astType );
		dumpParameterStr( "struct " );
		if( astSym != 0 ){
			dumpParameterStr(  CSymbol.getName(astSym) );
		}
		dumpParameterStr( "{" );
		if( stunlvl < 1 ){
			astDefChain = CTypeInfo.getMemberChain( astType );
			while( astDefChain )
			{
				astIdx = CUniteChain.getSymbol( astDefChain);
				if( astIdx )
				{
					astMemType = CSymbol.getType( astIdx );
					ccOutputTypeNamePrefix( astMemType, stunlvl+1 );
					dumpParameterStr(" ");
					dumpParameterStr(  CSymbol.getName( astIdx ) );
					ccOutputTypeNamePostfix( astMemType );
					dumpParameterStr(  ";" );
				}
				astDefChain = CUniteChain.getNextOne( astDefChain );
			}
		}
		dumpParameterStr(  "}" );
	}
	else if( CTypeInfo.isUnion( astType )  )
	{
		AST astSym = CTypeInfo.getTagInfo( astType );
		dumpParameterStr( "union " );
		if( astSym != 0 ){
			dumpParameterStr(  CSymbol.getName(astSym) );
		}
		dumpParameterStr( "{" );
		if( stunlvl < 1 ){
			astDefChain = CTypeInfo.getMemberChain( astType );
			while( astDefChain )
			{
				astIdx = CUniteChain.getSymbol(astDefChain) ;
				if( astIdx )
				{
					astMemType = CSymbol.getType( astIdx );
					ccOutputTypeNamePrefix( astMemType, stunlvl+1 );
					dumpParameterStr(" ");
					dumpParameterStr(  CSymbol.getName( astIdx ) );
					ccOutputTypeNamePostfix( astMemType );
					dumpParameterStr(  ";" );
				}
				astDefChain = CUniteChain.getNextOne( astDefChain );
			}
		}
		dumpParameterStr(  "}" );
	}
	else if( CTypeInfo.isEnum( astType ) )
	{
		AST astSym = CTypeInfo.getTagInfo( astType );
		dumpParameterStr( "enum " );
		if( astSym != 0 ){
			dumpParameterStr(  CSymbol.getName( astSym )  );
		}
	}
	else if( CTypeInfo.isFunction( astType )  )
	{
		astOrg = CTypeInfo.getElementType( astType );
		if( astOrg )
		{
			ccOutputTypeNamePrefix( astOrg, stunlvl );
		}
	}
	else if( CTypeInfo.isBitfield( astType )   )
	{
		astOrg = CTypeInfo.getElementType( astType );
		if( astOrg )
		{
			ccOutputTypeNamePrefix( astOrg, stunlvl );
		}
	}else{
		dumpParameterStr( dumpGetStr( XML_ERROR ) );
	}
}
static VOID dumpType( AST astType ){
	sprintf( tempBuf, header_format, dumpGetStr( XML_RECORD ), astType );
	dumpOutputStream( tempBuf );

	sprintf( tempBuf, sub_value_header_format, dumpGetStr(XML_NAME), "" );
	dumpOutputStream( tempBuf );

	ccOutputTypeNamePrefix( astType, 0 );
	ccOutputTypeNamePostfix( astType );
	sprintf( tempBuf, sub_value_tail_format, dumpGetStr(XML_NAME)  );
	dumpOutputStream( tempBuf );

	ccOutputTypeNamePrefix( astType, 0 );
	ccOutputTypeNamePostfix( astType );

	sprintf( tempBuf, sub_value_tail_format, dumpGetStr(XML_NAME)  );
	dumpOutputStream( tempBuf );

	sprintf( tempBuf, tail_format, dumpGetStr( XML_RECORD ) );
	dumpOutputStream( tempBuf );
}
VOID DumpType( PSZ szPath, PSZ postfix ){
	AST astType;
	AST astMax;

	if( szPath == NULL ){
		return;
	}
	strcpy( file_buf, szPath );
	file_buf[strlen(szPath)] = '\0';
	strcat(file_buf, postfix );
	file_buf[strlen(szPath)+strlen(postfix)] = '\0';
	if( COEXIT_SUCCESS == dumpOutputStreamInit_file(file_buf)){
		astType = MIN_ARRAY;
		astMax = CTypeInfo.getMax();
		sprintf( tempBuf, top_header, dumpGetStr(XML_TYPE) );
		dumpOutputStream( tempBuf );
		while( astType <= astMax ){
			dumpType( astType );
			astType ++;
		}
		sprintf( tempBuf, top_end, dumpGetStr(XML_TYPE) );
		dumpOutputStream( tempBuf );
		dumpOutputStreamEnd_file();
	}
}

